package org.tgit.gateway.controller;


import java.time.Duration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.codec.ServerSentEvent;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.tgit.gateway.common.ApiConstants;
import org.tgit.gateway.common.CommonUtil;
import org.tgit.gateway.common.GatewayException;
import org.tgit.gateway.common.TgitResponse;
import org.tgit.gateway.domain.ReqServiceAuthorize;
import org.tgit.gateway.domain.ReqServiceRegister;
import org.tgit.gateway.domain.ServiceAuthorize;
import org.tgit.gateway.service.GatewayService;

import io.netty.util.internal.ThreadLocalRandom;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.function.Tuples;

/**
 * 
 * @author fanzaijun
 * 2017年6月27日
 */
@Api(value = "API网关接口服务")
@RestController
@RequestMapping("/rest/gateway/manager")
public class GatewayController {
    @Autowired
    private GatewayService gatewayService;
    
    /**
     * 
    * @Title: apiGateWayErrorInfo   
    * @Description: TODO(网关授权错误)
    * @author fanzaijun  
    * @date 2018年8月24日 下午3:03:45   
    * @return  
    * Mono<TgitResponse>  
    * @throws (没有异常抛出)
     */
    @ApiOperation(notes = "网关错误返回", value = "网关错误返回" , httpMethod = "POST")
    @RequestMapping(value = "/error/{id}")
    public Mono<TgitResponse> apiGateWayErrorInfo(@PathVariable("id") String id ){
    	TgitResponse tgitResponse=new TgitResponse();
    	tgitResponse.setMessage(ApiConstants.ERROR_MAP.get(id));
    	return Mono.just(tgitResponse);
    }
    
    /**
     * 重新加载APP下的API鉴权信息到网关
    * @Title: reloadAllAppApiInfo   
    * @Description: 重新加载APP下的API鉴权信息到网关
    * @author fanzaijun  
    * @date 2018年10月26日 下午5:29:34   
    * @return  
    * Mono<TgitResponse>  
    * @throws (没有异常抛出)
     */
    @ApiOperation(notes = "重新加载APP下的API鉴权信息到网关", value = "重新加载APP下的API鉴权信息到网关" , httpMethod = "POST")
    @PostMapping(value = "/reloadAllAppApiInfo")
    public Mono<TgitResponse> reloadAllAppApiInfo(){
    	//业务处理
    	gatewayService.reloadAllAppApiInfo();
    	//返回结果
    	 return Mono.just(TgitResponse.success());
    }
    
    /**
     * 重新加载API所有信息到网关
    * @Title: reloadAllApiInfo   
    * @Description: 重新加载API所有信息到网关
    * @author fanzaijun  
    * @date 2018年10月26日 下午5:29:17   
    * @return  
    * Mono<TgitResponse>  
    * @throws (没有异常抛出)
     */
    @ApiOperation(notes = "重新加载API所有信息到网关", value = "重新加载API所有信息到网关", httpMethod = "POST")
    @RequestMapping(value = "/reloadAllApiInfo", method = RequestMethod.POST)
    public Mono<TgitResponse> reloadAllApiInfo(){
    	//业务处理
    	gatewayService.reloadAllApiInfo();
    	//返回结果
        return Mono.just(TgitResponse.success());
    }
    
    /**
     * 
    * @Title: serviceApiRegister   
    * @Description: api注册
    * @author fanzaijun  
    * @date 2018年10月26日 下午5:28:04   
    * @param req
    * @return  
    * Mono<TgitResponse>  
    * @throws (没有异常抛出)
     */
    @ApiOperation(notes = "API注册", value = "注册API信息", httpMethod = "POST")
    @RequestMapping(value = "/serviceApiRegister", method = RequestMethod.POST)
    public Mono<TgitResponse> serviceApiRegister(@RequestBody ReqServiceRegister req) {
    	  if (req == null){
              throw new GatewayException(ApiConstants.PARAM_FORMAT_ERROR);
          }
          String[] apiIds = req.getApiIds();
          if (CommonUtil.isEmpty(apiIds)){
              throw new GatewayException(ApiConstants.PARAM_FORMAT_ERROR,"传入的APIID列表为空");
          }
          gatewayService.registerApi(apiIds);
    	 return Mono.just(TgitResponse.success());
    }
    
    /**
     * 开启或关闭API服务
    * @Title: switchApiService   
    * @Description: 开启或关闭API服务
    * @author fanzaijun  
    * @date 2018年10月26日 下午5:29:54   
    * @return  
    * Mono<TgitResponse>  
    * @throws (没有异常抛出)
     */
    @ApiOperation(notes = "开启或关闭API服务", value = "开启或关闭API服务", httpMethod = "POST")
    @RequestMapping(value = "/switchApiService", method = RequestMethod.POST)
    public Mono<TgitResponse> switchApiService() {
    	
    	 return Mono.just(TgitResponse.success());
    }
    
    /**
     * API授权
    * @Title: serviceAuthorize   
    * @Description: API授权
    * @author fanzaijun  
    * @date 2018年10月26日 下午5:30:06   
    * @return  
    * Mono<TgitResponse>  
    * @throws (没有异常抛出)
     */
    @ApiOperation(notes = "API授权", value = "授权APP访问API", httpMethod = "POST")
    @RequestMapping(value = "/serviceAuthorize", method = RequestMethod.POST)
    public  Mono<TgitResponse> serviceAuthorize(@RequestBody ReqServiceAuthorize req){
    	 if (req == null){
             throw new GatewayException(ApiConstants.PARAM_FORMAT_ERROR);
         }
         ServiceAuthorize[] apiAuth = req.getAuths();
         //为空处理
         if (CommonUtil.isEmpty(apiAuth)){
             throw new GatewayException(ApiConstants.PARAM_FORMAT_ERROR,"传入的ServiceAuthorize数组对象为空");
         }
         gatewayService.serviceAuthorize(apiAuth);
    	 return Mono.just(TgitResponse.success());
    }
    
    
    /**
     *
    * @Title: randomNumbers   
    * @Description: TODO(随机数返回)
    * @author fanzaijun  
    * @date 2018年8月20日 下午6:10:20   
    * @return  
    * Flux<ServerSentEvent<Integer>>  
    * @throws (没有异常抛出)
     */
    @GetMapping("/randomNumbers")
    public Flux<ServerSentEvent<Integer>> randomNumbers() {
    	 return Flux.interval(Duration.ofSeconds(1))
                 .map(seq -> Tuples.of(seq, ThreadLocalRandom.current().nextInt()))
                 .map(data -> ServerSentEvent.<Integer>builder()
                         .event("random")
                         .id(Long.toString(data.getT1()))
                         .data(data.getT2())
                         .build());
    }
}